package eventx

import (
	"math"
)

func newDispatcher(event string) *Dispatcher {
	dispatcher := &Dispatcher{}
	dispatcher.eventName = event
	dispatcher.listenerList = []*Event{}
	dispatcher.bufList = []*Event{}
	return dispatcher
}

type Dispatcher struct {
	// 主体
	host interface{}
	// 事件名字
	eventName string
	/// 事件的侦听列表
	listenerList []*Event
	/// 引入buf，避免创建太多的数组对象
	bufList []*Event

	lastEventOn *Event
	//
	idCount int
}

func (dispatcher *Dispatcher) Dispose() {
	if dispatcher == nil {
		return
	}
	dispatcher.OffAll()
	dispatcher.lastEventOn = nil
	dispatcher.bufList = nil
	dispatcher.listenerList = nil
}

func (dispatcher *Dispatcher) OnKey(handlerKey string, priority int, params ...interface{}) (event *Event) {
	handler := keyToHandler[handlerKey]
	return dispatcher.createListener(handler, priority, false, params...)
}

// On 添加类型为[type]，处理方法为[handler]的监听器，优先级[priority]的数值越大，越早触发
// 返回event用于避免重复监听
func (dispatcher *Dispatcher) On(handler Handler, priority int, params ...interface{}) (event *Event) {
	return dispatcher.createListener(handler, priority, false, params...)
}

func (dispatcher *Dispatcher) Once(handler Handler, priority int, params ...interface{}) (event *Event) {
	return dispatcher.createListener(handler, priority, true, params...)
}

func (dispatcher *Dispatcher) createListener(handler Handler, priority int, once bool, params ...interface{}) (event *Event) {
	if handler == nil {
		panic("#GetDispatcher.On() error: handler is nil")
	}

	var list = dispatcher.listenerList
	var item = &Event{}
	item.dispatcher = dispatcher
	dispatcher.idCount++
	item.id = dispatcher.idCount
	dispatcher.lastEventOn = item
	item.priority = priority
	item.handler = handler
	item.OnParams = params
	item.isOnce = once

	var index = 0
	for i := len(list) - 1; i >= 0; i-- {
		if priority > list[i].priority {
			index = i + 1
			break
		}
	}

	index = int(math.Max(float64(0), float64(index)))
	list = append(list, nil)
	copy(list[index+1:], list[index:])
	list[index] = item
	dispatcher.listenerList = list

	return item
}

func (dispatcher *Dispatcher) Off(event *Event) {
	var list = dispatcher.listenerList
	if list == nil {
		return
	}
	if len(list) == 0 {
		return
	}

	var index = -1
	var remove *Event
	for i, e := range list {
		if e.id == event.id {
			index = i
			remove = event
			break
		}
	}
	if index == -1 {
		return
	}

	remove.isRemoved = true
	remove.Reset()
	dispatcher.listenerList = append(list[:index], list[index+1:]...)
}

func (dispatcher *Dispatcher) OffAll() {
	if dispatcher == nil {
		return
	}
	dispatcher.listenerList = []*Event{}
}

// Dispatch / 派发消息，实现了冒泡
func (dispatcher *Dispatcher) Dispatch(params ...interface{}) (err error) {
	return dispatcher.dispatchBubble(params)
}

/// 事件冒泡
func (dispatcher *Dispatcher) dispatchBubble(params []interface{}) error {
	var list = dispatcher.listenerList
	if list != nil {
		var buf = dispatcher.bufList
		for {
			if len(list) <= 0 {
				break
			}
			var item = list[len(list)-1]
			list = list[:len(list)-1]
			// 如果事件已经标记删除，不触发事件处理，继续下一个
			if item.isRemoved == true {
				continue
			}

			item.DispatchParams = params
			// 触发事件的处理函数
			err := item.handler(item)
			if err != nil {
				return err
			}

			// 只执行一次
			if item.isOnce {
				dispatcher.Off(item)
			}
			// 避免内存泄漏
			item.DispatchParams = nil
			// 如果事件没有标记删除，添加到缓存中
			if item.isRemoved == false {
				buf = append(buf, nil)
				copy(buf[1:], buf[0:])
				buf[0] = item
			}
		}
		// 设置事件kind指向缓存列表
		dispatcher.listenerList = buf
		// 旧的，已经遍历完成的当前列表，放入缓存中
		dispatcher.bufList = list
	}

	return nil
}
